package com.wjm.blog.common.util;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

/**
 * @Description: JSON序列化
 */
public class JsonUtils {

    private static Logger logger = LoggerFactory.getLogger(JsonUtils.class);

    private static ObjectMapper objectMapper = new ObjectMapper();

    private static ObjectMapper objectMapperNonNull = new ObjectMapper();
	private static ObjectMapper objectMapperUnknownProperties = new ObjectMapper()
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);


    static {
        objectMapperNonNull.setSerializationInclusion(Include.NON_NULL);
    }

    /**
     * @Description: 将json字符串读为java对象
     */
    public static <T> T read(String content, Class<T> valueType) {
        try {
            return objectMapper.readValue(content, valueType);
        } catch (Exception e) {
            logger.error("error on read json [" + content + "]", e);
            throw new RuntimeException("error on read json", e);
        }
    }

    /**
     * @Description: 将json字符串读为java对象, 支持复杂泛型
     */
    public static <T> T read(String content, TypeReference<T> valueTypeRef) {
        try {
            return objectMapper.readValue(content, valueTypeRef);
        } catch (Exception e) {
            logger.error("error on read json [" + content + "]", e);
            throw new RuntimeException("error on read json", e);
        }
    }

    /**
     * @Description: 将json字符串读为java对象集合
     */
    public static <T> List<T> readList(String content, Class<T> valueType) {
        try {
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, valueType);
            return objectMapper.readValue(content, javaType);
        } catch (Exception e) {
            logger.error("error on read json [" + content + "]", e);
            throw new RuntimeException("error on read json", e);
        }
    }

    /**
     * @Description: 反序列化为Map
     * @date 2015年7月14日上午11:22:03
     * @version 2.2.0
     */
    public static Map<?, ?> readAsMap(String content) {
        return read(content, Map.class);
    }

    /**
     * @Description: 将java对象写为json字符串
     */
    public static String write(Object value) {
        try {
            return objectMapper.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            logger.error("error on write json", e);
            throw new RuntimeException("error on write json", e);
        }
    }

    public static String writeExcludeNull(Object value) {
        try {
            return objectMapperNonNull.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            logger.error("error on write json", e);
            throw new RuntimeException("error on write json", e);
        }
    }

    /**
     * getJsonNode(获得json每个节点)
     *
     * @param content
     * @return 设定文件
     * JsonNode    返回类型
     * @throws
     * @Title: getJsonNode
     * @Description: 获得json每个节点
     */
    public static JsonNode getJsonNode(String content) {
        try {
            return objectMapper.readTree(content);
        } catch (Exception e) {
            logger.error("error on getJsonNode", e);

            throw new RuntimeException("error on getJsonNode", e);
        }
    }

    /**
     * getStringNodeValue(获得json串中指定string类型的节点值)
     *
     * @param content json串
     * @param key     获得的key
     * @return 设定文件
     * String    返回类型
     * @throws
     * @Title: getStringNodeValue
     * @Description: 获得json串中指定string类型的节点值
     */
    public static String getStringNodeValue(String content, String key) {
        return getJsonNode(content).get(key).asText();
    }

    /**
     * getBooleanNodeValue(获得json串中指定节点boolean类型的节点值)
     *
     * @param content json串
     * @param key     获得的key
     * @return 设定文件
     * Boolean    返回类型
     * @throws
     * @Title: getBooleanNodeValue
     * @Description: 获得json串中指定节点boolean类型的节点值
     */
    public static Boolean getBooleanNodeValue(String content, String key) {
        return getJsonNode(content).get(key).asBoolean();
    }

    /**
     * getIntNodeValue(获得json串中指定节点int类型的节点值)
     *
     * @param content json串
     * @param key     获得的key
     * @return 设定文件
     * int    返回类型
     * @throws
     * @Title: getIntNodeValue
     * @Description: 获得json串中指定节点int类型的节点值
     */
    public static int getIntNodeValue(String content, String key) {
        return getJsonNode(content).get(key).asInt();
    }

    /**
     * getDoubleNodeValue(获得json串中指定节点Double类型的节点值)
     *
     * @param content json串
     * @param key     获得的key
     * @return 设定文件
     * Double    返回类型
     * @throws
     * @Title: getDoubleNodeValue
     * @Description: 获得json串中指定节点Double类型的节点值
     */
    public static Double getDoubleNodeValue(String content, String key) {
        return getJsonNode(content).get(key).asDouble();
    }

    /**
     * getLongNodeValue(获得json串中指定节点Long类型的节点值)
     *
     * @param content json串
     * @param key     获得的key
     * @return 设定文件
     * Long    返回类型
     * @throws
     * @Title: getLongNodeValue
     * @Description: 获得json串中指定节点Long类型的节点值
     */
    public static Long getLongNodeValue(String content, String key) {
        return getJsonNode(content).get(key).asLong();
    }
	/**
	 * @Description: 将json字符串读为java对象,支持属性不对应
	 */
	public static <T> T readAsClass(String content, Class<T> valueType) {
		try {
			return objectMapperUnknownProperties.readValue(content, valueType);
		} catch (Exception e) {
			logger.error("error on read json [" + content + "]", e);
			throw new RuntimeException("error on read json", e);
		}
	}
	
	public static String writeFormatDate(Object value) {
		try {
			objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
			return objectMapper.writeValueAsString(value);
		} catch (JsonProcessingException e) {
			logger.error("error on write json", e);
			throw new RuntimeException("error on write json", e);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> List<T> convertToList(String str,Class obj){
		return readList(str, obj);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> List<T> convertToList(List list,Class obj){
		return readList(writeFormatDate(list), obj);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> T convertToBean(Object preObj,Class obj) {
		return (T) read(writeFormatDate(preObj),obj);
	}
}
